-----------------------------------------------------------
-- 英雄格子相关

-- createHeroGrid 				创建英雄对象
-- getCacheHeroGrid 			获取通用缓存英雄对象
-- getHeroGridCalcCache 		临时计算用的英雄格子
-- createOthers 				有时候要给HeroSimple额外附上一些特殊值，如等级血量等，会用到
-- makeHeroSimple 				根据英雄对象封装英雄信息HeroSimple
-- makeHeroSimpleByID 			根据英雄id封装英雄信息HeroSimple
-- makeHeroSimpleByMonsterID 	根据怪物id封装英雄信息HeroSimple
-- makeHeroStatic				根据英雄id封装英雄静态信息HeroStatic
-- makeHeroDynamic 				根据英雄对象封装英雄动态信息HeroDynamic
-- makeHeroDynamicByID 			根据英雄id封装英雄动态信息HeroDynamic
-- makeHeroInfo 				根据英雄id封装英雄基础信息
-- makeMonsterSimpleData 		根据怪物id封装
-- makeHeroNice 				封装特殊英雄信息
-- getMaxQuality 				根据星级获取英雄最高品阶
-- getMaxLv 					根据星级和品阶获取英雄最大等级
-- getHeroBodyById				根据英雄id获取英雄形象body
-----------------------------------------------------------

local lua_mongo = _G.lua_mongo
local Util = require("common.Util")
local UpNeedExcel = require("excel.upNeed")
local HeroExcel = require("excel.hero")
local MonsterExcel = require("excel.monster")
local ObjHuman = require("core.ObjHuman")
local RoleDefine = require("role.RoleDefine")
local HeroDefine = require("hero.HeroDefine")
local HeroLogic = require("hero.HeroLogic")
local RoleAttr = require("role.RoleAttr")
local EquipExcel = require("excel.equip")
local ItemDefine = require("bag.ItemDefine")
local BagLogic = require("bag.BagLogic")
local Grid = require("bag.Grid")
local SkinLogic = require("skin.SkinLogic")
local PaomaExcel = require("excel.paoma")
local UnionTecLogic = require("union.UnionTecLogic")
local HeroBook = require("hero.HeroBook")
local XingYaoGongMing = require("xingYaoMen.XingYaoGongMing")
local FuwenExcel = require("excel.fuwen").fuwen

HERO_GRID_CACHE = HERO_GRID_CACHE or {} -- 为静态英雄数据使用
HERO_GRID_CACHE_TUJIAN = HERO_GRID_CACHE_TUJIAN or {}

HERO_LEVELUP_MAXCNT = 5 		-- 最多连升x次
HERO_LEVELUP_MAXLEVEL = 60 		-- 从x级开始不能连续升多级

-- 创建一个英雄grid
function createHeroGrid(id,star)
	local cf = HeroExcel.hero[id]
	if not cf then 
	   assert(nil, "not hero id "..id)
	   return 
	end	
		
	local grid = {}
	grid.uuid = lua_mongo.id()		--唯一标识
	grid.id = id
	grid.lv = 1						--等级
    -- 星级调整成动态值 dxzeng九零  一 起玩 www.9  01 7  5.com 
    grid.star = star or cf.star				--星级 起始星级
	grid.quality = 0  			    --品质
	grid.zhandouli = 0				--战斗力 
	grid.equip = nil				--装备 1-6对应6个部位	
	grid.shuijingAttrID = nil       --水晶随机属性ID	
    grid.fuwen = nil                --符文 1-2对应2个符文   因为只凭一个id或一个索引无法的到所上符文的详细信息
    grid.bingshu = nil 				--兵书 [index] = bingshuGrid
    grid.oldLV = nil 				--星耀共鸣记录旧等级
    grid.oldQuality = nil 			--星耀共鸣记录旧品质	
	return grid	
end

-- 初始化的英雄 无添加
function getCacheHeroGrid(id, star, others)
	if not id then return end
	local cf = HeroExcel.hero[id]
    if not cf then return end

    star = star or cf.star
	local grid = HERO_GRID_CACHE[id] and HERO_GRID_CACHE[id][star] or nil
	if not grid or others then
		if not cf then return end
		local grid = createHeroGrid(id, star)
        if others then
		   grid.lv = others.lv and others.lv or grid.lv
		   grid.quality = others.quality and others.quality or grid.quality
           grid.star = others.star and others.star or grid.star
        end

		grid.attrs = Util.copyTable(RoleAttr.calcHeroGrid(grid))
		grid.zhandouli = grid.attrs[RoleDefine.ZHANDOULI] or 0	
		HERO_GRID_CACHE[id] = HERO_GRID_CACHE[id] or {}		
        HERO_GRID_CACHE[id][star] = grid
	end
	return HERO_GRID_CACHE[id][star]
end

-- 图鉴的英雄，经过美化
function getCacheHeroGridTujian(id)
	if not id then return end
	local grid = HERO_GRID_CACHE_TUJIAN[id]
	if not grid then
		local cf = HeroExcel.hero[id]
		if not cf then return end		

		local grid = createHeroGrid(id,cf.star)
		local maxQuality = getMaxQuality(cf.star) 
		grid.lv = getMaxLv(cf.star, maxQuality)
		grid.quality = maxQuality

        -- 星级调整成动态值 dxzeng
        grid.star = cf.star

		grid.attrs = Util.copyTable(RoleAttr.calcHeroGrid(grid))
		grid.zhandouli = grid.attrs[RoleDefine.ZHANDOULI] or 0

		-- 英雄如果有推荐，用推荐
		local scf = HeroExcel.strategy[cf.id]
		local equipLen = scf and #scf.equips or 0
        for i = 1, equipLen do
            grid.equip = grid.equip or {}
            grid.equip[i] = scf.equips[i]

            if i == ItemDefine.EQUIP_SUBTYPE_SHUIJIN then
	            grid.shuijingAttrID = scf.shuijing
            end
        end				
		HERO_GRID_CACHE_TUJIAN[id] = grid		
	end
	return HERO_GRID_CACHE_TUJIAN[id]
end

-- 临时用的英雄
local HERO_GRID_CALC_CACHE = {}
function getHeroGridCalcCache(grid)
	Util.cleanTable(HERO_GRID_CALC_CACHE)
	Util.copyTableSimple(grid, HERO_GRID_CALC_CACHE)
	return HERO_GRID_CALC_CACHE
end

-- 根据id取形象
function getHeroBodyById(id)
	local cf = HeroExcel.hero[id]
	if not cf then
		return 0
	end
	return cf.body
end

-- 获取英雄最高品阶
function getMaxQuality(star)
	local starConfig  = HeroExcel.star[star]
	if not starConfig then return 0 end
	local maxQuality = starConfig.maxQuality
	return maxQuality
end

-- 获取英雄最高等级
function getMaxLv(star, quality)
	local starConfig  = HeroExcel.star[star]
	if not starConfig then return 0 end
	if not starConfig.maxLv[quality+1] then
		return starConfig.maxLv[#starConfig.maxLv][2]
	end
	local maxLv = starConfig.maxLv[quality+1][2]
	return maxLv
end

-- 获取英雄等级 能达到的最高品阶
function getMaxQualityByLv(star, lv)
	local maxQuality = getMaxQuality(star)
	local starConfig  = HeroExcel.star[star]
	if not starConfig then return 0 end

	local quality = 0
	for i = 1, maxQuality do 
		local maxLv = getMaxLv(star, quality)
		if lv >= maxLv then
			quality = i
		else
			break
		end
	end
	return quality <= maxQuality and quality or maxQuality
end

-- 额外数据
local TEMP_OTHERS = {}
function createOthers(lv, hp, hpMax, star)
	TEMP_OTHERS.lv = lv 
	TEMP_OTHERS.hp = hp 
	TEMP_OTHERS.hpMax = hpMax
    TEMP_OTHERS.star = star
    TEMP_OTHERS.quality = getMaxQuality(star)
	return TEMP_OTHERS
end

-- 封装英雄信息
function makeHeroSimple(net, grid, index, human, others, tuJian)
	local id = grid and (grid.id or grid.heroID) 
	local cf = id and HeroExcel.hero[id]
    local star = grid and grid.star or (cf and cf.star or 1)
	local upStarConfig = HeroDefine.getNextAttrConfig(id, star)	
	local jobConfig = cf and cf.job and HeroExcel.job[cf.job]
    local isGongMing = XingYaoGongMing.isGongMing(human, index)

	net.id = id or 0
	net.index = index or 0
    net.uuid = grid and grid.uuid or ""
	net.gl = cf and cf.gl or 0
	net.camp = cf and cf.camp or 0
	net.job = cf and cf.job or 0
	net.star = others and others.star or star --cf and cf.star or 0 星级调整 dxzeng  
	net.icon = grid and grid.head or (cf and cf.head or 0)
	net.body = grid and grid.body or (cf and cf.body or 0)
	if grid and human and index then  -- todo 皮肤这个以后可能还是需要继续整理
		local skinConf = SkinLogic.getHeroSkin(human, index)
		if skinConf then
			net.icon = skinConf.head
			net.body = skinConf.body
		end
	end	
	net.up =  upStarConfig == nil and 0 or 1 --是否能够升星

	net.lv = others and others.lv or (grid and grid.lv or 1)
	net.zhandouli = grid and grid.zhandouli or 0
	net.quality = grid and grid.quality or 0
	net.isLock = (grid and grid.isLock) and 1 or 0
	net.hp = others and others.hp or 0		
	net.hpMax = others and others.hpMax or 0	
	net.cnt = others and others.cnt or 1
	net.isget = HeroBook.isGetHero(human, id) or 0
	net.weightLv = cf and cf.grade or 0
	net.name = cf and cf.name or ""
	net.grade = cf and cf.grade or 0
	net.jobDesc = jobConfig and jobConfig.desc or ""
    net.label = cf and cf.label or ""
    net.order = cf and cf.order or 0
    net.isGongMing = isGongMing or 0
    
    
    --是否发送图鉴信息
    net.general[0] = 0
    if tuJian then
        local tj = HeroExcel.tujian[id]
        if tj ~= nil then
            net.general[0] = 1
            net.general[1].cm = tj.cm or 0
            net.general[1].kg = tj.kg or 0
            net.general[1].age = tj.age or 0
            net.general[1].cup = tj.cup or ""
            net.general[1].character = tj.character or ""
            net.general[1].interest = tj.interest or ""
            net.general[1].desc = tj.desc or ""
        end
    end
end

-- 封装英雄信息装备符文
function fontHeroDetailInfo(net, grid, index, human, others, tuJian)
	makeHeroSimple(net,grid, index, human, others, tuJian)
    net.equips = grid.equip or {}
    for k,v in pairs(net.equips) do
        if next(v) then
            v.name = EquipExcel.equip[v.id].name
        end
    end
    net.fuWens = grid.fuwen or {}
    for k,v in pairs(net.fuWens) do
        if next(v) then
            v.name = FuwenExcel[v.id].name
        end
    end
end

-- 根据英雄id封装英雄信息heroSimple
function makeHeroOrMonster(net, id, index, others, human,tujian)
	local grid = getCacheHeroGrid(id)
    if not grid then
       makeHeroSimpleByMonsterID(net, id, others)
    else
       makeHeroSimple(net, grid, index, human, others,tujian)
    end
end

-- 根据英雄id封装英雄信息heroSimple
function makeHeroSimpleByID(net, id, index, others, human, tujian)
    local star = others and others.star or nil
	local grid = getCacheHeroGrid(id, star, others)
	makeHeroSimple(net, grid, index, human, others,tujian)
end

-- 根据怪物id封装英雄信息
function makeHeroSimpleByMonsterID(net, id, others)
	makeHeroSimpleByID(net, nil, nil, others)

	local mcf = MonsterExcel.monster[id]
	if not mcf then return end

	net.id = id	
	net.camp = mcf.camp
	net.job = mcf.job
	net.star = mcf.star
	net.icon = mcf.head
	net.body = mcf.body
	net.lv = others and others.lv or 1
	net.hp = others and others.hp or 0		
	net.hpMax = others and others.hpMax or 0
end

function makeHeroSimpleByGeneral(net, id)
	local tj = HeroExcel.tujian[id]
	if tj ~= nil then
		net.general[0] = 1
		net.general[1].cm = tj.cm or 0
		net.general[1].kg = tj.kg or 0
		net.general[1].age = tj.age or 0
		net.general[1].cup = tj.cup or ""
		net.general[1].character = tj.character or ""
		net.general[1].interest = tj.interest or ""
		net.general[1].desc = tj.desc or ""
	end
end

function makeHeroNice(net, id, cnt, isNew, index)
	net.itemData[0] = 0 
	net.heroSimple[0] = 0 
	net.heroStatic[0] = 0
	if cnt then
		net.itemData[0] = 1
		Grid.makeItem(net.itemData[1], id, cnt)	
	end
	local heroConfig = HeroExcel.hero[id]
	local specialConfig = HeroExcel.specialHero[id]
	if heroConfig then
		net.heroSimple[0] = 1
		makeHeroSimpleByID(net.heroSimple[1], id, index)

		net.heroStatic[0] = 1
		makeHeroStatic(net.heroStatic[1], id)
	end
	net.body = specialConfig and (heroConfig and heroConfig.body or 0) or 0
	net.isNew = isNew and 1 or 0
	net.weightLv = heroConfig and heroConfig.grade or 0
	net.attrs[0] = 0
	net.attrsMax[0] = 0
    net.bubble = ""
	if heroConfig then
        local bubble = PaomaExcel.bubble[heroConfig.id]
        net.bubble = bubble and bubble.drawCard or ""
		local heroGrid = getCacheHeroGridTujian(id)
		for key = RoleDefine.ATK, RoleDefine.SPEED do
			local value = heroGrid.attrs[key]
			net.attrs[0] = net.attrs[0] + 1
			net.attrs[net.attrs[0]].key = key
			net.attrs[net.attrs[0]].value = value

			net.attrsMax[0] = net.attrsMax[0] + 1
			net.attrsMax[net.attrsMax[0]].key = key
			net.attrsMax[net.attrsMax[0]].value = HeroDefine.getTujianMaxValue(key)
		end			
	end
end

-- 填充英雄详细信息：静态
function makeHeroStatic(net, id, tuJian)
	local cf = id and HeroExcel.hero[id]
	if not cf then 
       net.id=0
	   net.name =""
	   net.body =0
	   net.job = 0
	   net.weightLv=0
       net.normalAtkID=0
       net.skillList[0]=0
       net.beSkill[0]=0
       net.skin=0
       return 
    end
    local star = cf.star
    if tuJian and tuJian == 1 then
       local tuJianConfig = HeroExcel.tujian[id]
       if tuJianConfig then
          local maxStarIndex = #tuJianConfig.star
          star = tuJianConfig.star[maxStarIndex]
       end
    end

	net.id = id
	net.name = cf.name 
	net.body = cf.body
	net.job = cf.job
	net.weightLv = cf.grade  
	
    local attrConfig = HeroDefine.getAttrConfig(id, star)
    net.normalAtkID = attrConfig.normalAtkID


	net.skillList[0] = #attrConfig.skillList
	for i = 1, net.skillList[0] do
		HeroLogic.makeSkillNet(net.skillList[i], attrConfig.skillList[i])
	end

	net.beSkill[0] = #attrConfig.beSkillList    
	for i = 1, net.beSkill[0] do
		HeroLogic.makeSkillNet(net.beSkill[i], attrConfig.beSkillList[i])
	end
	net.skin = #cf.skin > 0 and 1 or 0	
end

-- 最多连续升x级
function getLevelUpCnt(human, nowLv, maxLv)	
	local cnt = 0
	local needJinbi = 0
	local needItemCnt = 0
	if human and human.db and human.db.bag then
		local bagItemCnt = BagLogic.getItemCnt(human, ItemDefine.ITEM_GREEN_EXP_ID)
		local bagJinbi = human.db.jinbi
		for i = 1,  HERO_LEVELUP_MAXCNT do
			local nextLv = nowLv + i
			local upcf = UpNeedExcel.upLv[nextLv]
			if not upcf then break end
			if nextLv > maxLv then break end

			if i > 1 then
				if (needJinbi + upcf.money > bagJinbi) or 
					(needItemCnt + upcf.soul > bagItemCnt) then
					break
				end
			end 

			cnt = cnt + 1
			needJinbi = needJinbi + upcf.money 
			needItemCnt = needItemCnt + upcf.soul

			if nowLv >= HERO_LEVELUP_MAXLEVEL then
				break  -- 小于一定等级不能连升
			end
		end
	end
	return cnt, needJinbi, needItemCnt
end

-- 填充英雄详细信息：动态
function makeHeroDynamic(net, grid, index, human)
	local id = grid and grid.id 
	local cf = id and HeroExcel.hero[id]
	local lv = grid and grid.lv or 1
	local star = grid and grid.star or 1 -- 星级调整成动态值 dxzeng --cf and cf.star or 0
	local quality = grid and grid.quality or 0 
	local maxLv = getMaxLv(star, quality)

    -- 最大品阶
    net.maxQuality = getMaxQuality(star)
	net.id = id or 0
	net.lv = lv
    net.uuid = grid and grid.uuid or ""
	net.head = cf and cf.head or 0
	net.quality = quality
	net.maxLv = maxLv	
	net.techLv = human and UnionTecLogic.getTechLvByJob(human, cf.job) or 0
    net.star = star
	net.upLv = 0
	if lv >= maxLv then -- 升阶
		local upcf = quality < getMaxQuality(star) and UpNeedExcel.upQuality[quality + 1]
		net.upLvJinbi = upcf and upcf.money or 0
		net.upLvSoul = upcf and upcf.jinjieshi or 0	
	else -- 升级
		if grid and human and index then
			net.upLv, net.upLvJinbi, net.upLvSoul = getLevelUpCnt(human, lv, maxLv)
		else
			local upcf = UpNeedExcel.upLv[lv + 1]
			net.upLvJinbi = upcf and upcf.money or 0
			net.upLvSoul = upcf and upcf.soul or 0	
		end	
	end	
	
	net.skin[0] = 0
	if grid and human and index then  -- todo 皮肤这个以后可能还是需要继续整理
		local skinConf, skinSkillConf = SkinLogic.getHeroSkin(human, index)
		if skinConf then
			net.head = skinConf.head
			net.skin[0] = 1  -- 皮肤技能相关
			local skinNet = net.skin[1]
			skinNet.name = skinConf.name
			skinNet.body = skinConf.body
			skinNet.normalAtkID = skinSkillConf.normalAtkID
			
			skinNet.skillList[0] = #skinSkillConf.skillList
			for i = 1, skinNet.skillList[0] do
				HeroLogic.makeSkillNet(skinNet.skillList[i], skinSkillConf.skillList[i])
			end

			skinNet.beSkill[0] = #skinSkillConf.beSkillID
			for i = 1, skinNet.beSkill[0] do
				HeroLogic.makeSkillNet(skinNet.beSkill[i], skinSkillConf.beSkillID[i])
			end
		end
	end

    -- 技能变更
    net.skillList[0] = 0
    net.beSkill[0] = 0
    if grid and grid.star ~= cf.star then
       local attrConfig = HeroDefine.getAttrConfig(id, grid.star)
       net.skillList[0] = #attrConfig.skillList
	   for i = 1, net.skillList[0] do
	   	  HeroLogic.makeSkillNet(net.skillList[i], attrConfig.skillList[i])
	   end
       
	   net.beSkill[0] = #attrConfig.beSkillList    
	   for i = 1, net.beSkill[0] do
	   	  HeroLogic.makeSkillNet(net.beSkill[i], attrConfig.beSkillList[i])
	   end
    end
    
	local attrs = nil	
	if human and index then
		attrs = ObjHuman.getHeroAttrs(human, index)  
	elseif grid and grid.attrs then
		attrs = grid.attrs
	end
	net.attrs[0] = 0
	if attrs then
		for key, value in pairs(attrs)do
	--		print("  net.attrs[0] ", net.attrs[0], key)
			if RoleDefine.isPanelAttr(key) or RoleDefine.isPingFenAttr(key) then
				net.attrs[0] = net.attrs[0] + 1
				net.attrs[net.attrs[0]].key = key
				net.attrs[net.attrs[0]].value = value
			end
		end	
	end	
	net.zhandouli = grid and grid.zhandouli or 0
end

-- 根据英雄id填充动态信息
function makeHeroDynamicByID(net, id,star)
	local grid = getCacheHeroGrid(id,star)
	makeHeroDynamic(net, grid)
end

-- 
function makeHeroInfo(net, grid)
	local id = grid and grid.id 
	local cf = id and HeroExcel.hero[id]	
	net.id = id or 0
	net.camp = cf and cf.camp or 0
	net.icon = cf and cf.head or 0
	net.lv = grid and grid.lv or 0
	net.star = grid and grid.star or 0
	net.label = cf and cf.label or ""
end

function makeMonsterSimpleData(net, id, lv)
	local mcf = MonsterExcel.monster[id]
	if not mcf then return end
	net.id = id or 0
	net.icon = mcf.head
	net.lv = lv or 1
	net.camp = mcf.camp 
	net.star = mcf.star 
	net.label = mcf and mcf.label or ""
	return true
end


function getMonsterOutIDBody(id)
	local monsterOutConfig = MonsterExcel.monsterOut[id]
	if not monsterOutConfig then return 0 end

	local monsterID = monsterOutConfig.member[1][1]
	local monsterConfig = MonsterExcel.monster[monsterID]
	if not monsterConfig then return 0 end
	return monsterConfig.body
end


